package demo.using.trans;

import com.alibaba.fastjson.JSON;

import java.beans.BeanInfo;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author : GuoFei
 * @date : 2019/3/22 13:47
 */
public class MapAddObj {

    public static void main(String[] args) {
        List<Map<String,Object>> listMap = new ArrayList<>();
        for (int i = 0; i < 10; i++) {
            Map<String, Object> dataMap = new HashMap<>();
            dataMap.put("id", i);
            dataMap.put("name", "name" + i);
            dataMap.put("success", i % 2 == 0);
            listMap.add(dataMap);
        }

        // 转化为对象列表
        List<TestUserBO> listUserObj = listMapToListObj(listMap, TestUserBO.class);
        System.out.println(JSON.toJSONString(listUserObj));

        // 转化为Map列表
        List<Map> listUserMap = listObjToListMap(listUserObj);
        System.out.println(JSON.toJSONString(listUserMap));
    }

    public static <T> List<T> listMapToListObj(List<Map<String,Object>> listMap, Class<T> t) {
        List<T> listObj = new ArrayList<>();

        listMap.forEach(s -> {
            try {
//                listObj.add(mapToObject1(s, t));
//                listObj.add(mapToObject2(s, t));
                listObj.add(mapToObject3(s, t));
            } catch (Exception e) {
                e.printStackTrace();
            }
        });

        return listObj;

    }

    public static List<Map> listObjToListMap(List listObj){
        List<Map> newMap = new ArrayList<>();
        listObj.forEach(s-> {
            try {
//                newMap.add(objectToMap1(s));
//                newMap.add(objectToMap2(s));
                newMap.add(objectToMap3(s));
            } catch (Exception e) {
                e.printStackTrace();
            }
        });
        return newMap;
    }

    public static Map<String,Object> objectToMap3(Object obj) throws Exception{
        Map<String,Object> map=new HashMap<>();
        BeanInfo beanInfo = Introspector.getBeanInfo(obj.getClass());
        PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors();
        for (PropertyDescriptor property : propertyDescriptors) {
            String key = property.getName();
            if (key.compareToIgnoreCase("class") == 0) {
                continue;
            }
            Method getter = property.getReadMethod();
            Object value = getter!=null ? getter.invoke(obj) : null;
            map.put(key, value);
        }
        return map;
    }

    public static <T> T mapToObject3(Map<String, Object> map, Class<T> clz) throws Exception{
        if (map == null)
            return null;
        Object obj = clz.newInstance();
        BeanInfo beanInfo = Introspector.getBeanInfo(obj.getClass());
        PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors();
        for (PropertyDescriptor property : propertyDescriptors) {
            Method setter = property.getWriteMethod();
            if (setter != null) {
                setter.invoke(obj, map.get(property.getName()));
            }
        }
        return (T) obj;
    }

    // 使用 java reflect
    public static Map<String,Object> objectToMap2(Object obj) throws Exception{
        Map<String,Object> map=new HashMap<String, Object>();
        Field[] fields = obj.getClass().getDeclaredFields();
        for(Field field:fields){
            field.setAccessible(true);
            map.put(field.getName(), field.get(obj));
        }
        return map;
    }

    // 使用 java reflect
    public static <T> T mapToObject2(Map<String, Object> map, Class<T> clz) throws Exception{
        Object obj = clz.newInstance();
        Field[] declaredFields = obj.getClass().getDeclaredFields();
        for(Field field:declaredFields){
            int mod = field.getModifiers();
            if(Modifier.isStatic(mod) || Modifier.isFinal(mod)){
                continue;
            }
            field.setAccessible(true);
            field.set(obj, map.get(field.getName()));
        }
        return (T) obj;
    }


    // 使用 BeanUtils
    public static <T> T mapToObject1(Map<String, Object> map, Class<T> t)
            throws Exception {
        if (map == null)
            return null;
        Object obj = t.newInstance();
        org.apache.commons.beanutils.BeanUtils.populate(obj, map);
        return (T) obj;
    }

    // 使用 BeanUtils
    public static Map<?, ?> objectToMap1(Object obj) {
        if (obj == null) {
            return null;
        }
        return new org.apache.commons.beanutils.BeanMap(obj);
    }
}
